#ifndef __LOGGER_H__
#define __LOGGER_H__

#include "util/util_config.h"
#include "util/object.h"

#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>

NS_UTIL_BEGIN

class LoggerTargetBase;
class Logger;


class LoggerTargetBase : public ObjectData
{
public:
	friend class Logger;
	typedef ObjectData base_type;

	static const int MSG = 0;
	static const int WRN = 1;
	static const int ERR = 2;
	static const int TMP = 3;
	static const int DBG = -1;
	static const int PRN = -2;

public:
	virtual void Log(int MSG_TYPE, const std::string& msg){}
	virtual void refresh(){}
	
public:
	LoggerTargetBase();
	virtual ~LoggerTargetBase();
};

class LoggerConsole : public LoggerTargetBase
{
public:
	typedef LoggerTargetBase base_type;
protected:
	std::vector<std::string> msg_buffer;
	std::mutex msg_mutex;

public:
	LoggerConsole(){}
	LoggerConsole(const LoggerConsole& loggerConsole):msg_buffer(loggerConsole.msg_buffer),msg_mutex(){}

public:
	virtual void Log(int MSG_TYPE, const std::string& msg);
	virtual void refresh();

public:

	virtual ~LoggerConsole();
};

class Logger
{
public:
	static const int MSG = 0;
	static const int WRN = 1;
	static const int ERR = 2;
	static const int TMP = 3;
	static const int DBG = -1;
	static const int PRN = -2;

public:
	Logger();
	~Logger();

protected:
	ObjectPtrT<LoggerTargetBase> target;

public:
	void LogMessage(const std::string& msg);
	void LogWarning(const std::string& msg);
	void LogError(const std::string& msg);
	void LogDebug(const std::string& msg);
	void LogPrint(const std::string& msg);		// without <CR>
	void LogPrintLine(const std::string& msg);	// with <CR>
	void LogPrintTmp(const std::string& msg);	// return <HOME> and print on the same line without <CR>

public:
	void SetData(LoggerTargetBase* logtarget);
	void refresh();


};


NS_UTIL_END


#endif